<?php

/**
 * 生成验证码
 *
 * @author haifeng.wu
 */

class Project_ImageCode
{
    /**
     *  @var $_width The width of the image,auto Calculated 验证图片宽度，程序自动计算
     */
    private $_width;

    /**
     *  @var $_height Image height 验证图片高度
     */
    private $_height;

    /**
     *  @var $_fontPath
     */
    private $_fontFilePath;

    /**
     *  @var $_fontSize
     */
    private $_fontSize;

    /**
     *  @var $_length Verification Code lenght 验证码长度
     */
    private $_length;


    /**
     *  @var $_dotNoise The number of noise 噪点数量
     */
    private $_dotNoise;

    /**
     *  @var $_lineNoise The number of noise lines 干扰线数量
     */
    private $_lineNoise;

    /**
     *  @var $_im image resource GD图像操作资源
     */
    private $_im;
   
    /**
     *  void Vcode::Vcode()
     *
     *  The constructor
     */
    public function __construct(){
        $this->_dotNoise = 20;//初始化噪点数量
        $this->_lineNoise = 2;//初始化干扰线数量
    }

     /**
     *  void Vcode::setLength(integer $length)
     *
     *  Set Verification Code length
     *  @access public
     *  @param integer $length;
     *  @return void
     */
    public function setLength($length){
        $this->_length = $length;
    }

    /**
     *  void Vcode::setDotNoise(integer $num)
     *
     *  How many noise dots want to draw
     *  @access public
     *  @param integer $num Too much will lower performance
     *  @return void
     */
    public function setDotNoise($num){
        $this->_dotNoise = $num;//手动设置噪点数量后，会覆盖初始设置
    }
    
    /**
     *
     *  设置字体
     *  @access public
     *  @param string $path
     *  @return void
     */
    public function setFontFilePath($path){
        $this->_fontFilePath = $path;
    }

    /**
     *
     *  设置字体
     *  @access public
     *  @param ingeger $size
     *  @return void
     */
    public function setFontSize($size){
        $this->_fontSize = $size;
    }
    
    /**
     *
     *  设置整体宽
     *  @access public
     *  @param ingeger $value
     *  @return void
     */
    public function setWidth($value){
        $this->_width = $value;
    }

    /**
     *
     *  设置整体高
     *  @access public
     *  @param ingeger $value
     *  @return void
     */
    public function setHeight($value){
        $this->_height = $value;
    }

    /**
     *  void Vcode::setLineNoise(integer $num)
     *
     *  How many noise lines want to draw
     *  @access public
     *  @param integer $num Too much will lower performance
     *  @return void
     */
    public function setLineNoise($num){
        $this->_lineNoise = $num;//手动设置干扰线数量后，会覆盖初始设置
    }

    /**
     *  String Vcode::randString()
     *
     *  Create Random characters 生成随机字符串
     *  @access private
     *  @return String
     */
    private function randString(){
        $strings = "ABCDEFGHJKLMNPQRSTUVWXYZ23456789";
        $string = '';
        for($i = 1; $i<=$this->_length; $i++) {
            $start = rand(1, strlen($strings));
            $string .= substr($strings, $start-1, 1);
        }
        return $string;
    }

    /**
     *  void Vcode::drawDot()
     *
     *  Draw dots noise 根据制定的数量随机画噪点，噪点颜色也随机
     *  @access private
     */
    private function drawDot(){
        for($i=0; $i<$this->_dotNoise; $i++){
            $color = imagecolorallocate($this->_im,
                                        mt_rand(0,255),
                                        mt_rand(0,255),
                                        mt_rand(0,255));//生成随机颜色
            imagesetpixel($this->_im,
                            mt_rand(0,$this->_width),
                            mt_rand(0,$this->_height),
                            $color);//在随机生成的坐标上画噪点
        }
    }

    /**
     *  void Vcode::drawLine()
     *
     *  Draw line noise 随机颜色随机画干扰线
     *  @access private
     */
    private function drawLine(){
        for($i=0; $i<$this->_lineNoise; $i++){
            $color = imagecolorallocate($this->_im,
                                        mt_rand(0,255),
                                        mt_rand(0,255),
                                        mt_rand(0,255));//随机生成颜色
            imageline($this->_im,
                        mt_rand(0,$this->_width),
                        mt_rand(0,$this->_height),
                        mt_rand(0,$this->_width),
                        mt_rand(0,$this->_height),
                        $color);//在随机生成的坐标上画干扰线
        }
    }

    /**
     *  String Vcode::paint()
     *
     *  Create image and output
     *  @access public
     *  @return string  The Verification Code to be encrypted by MD5
     */
    public function paint(){
   
        $this->_length = empty($this->_length) ? 4 : $this->_length;
        $this->_fontSize = empty($this->_fontSize) ? 12 : $this->_fontSize;
        $this->_width = empty($this->_width) ? $this->_length * ($this->_fontSize + 4) : $this->_width;
        $this->_height = empty($this->_height) ? 20 : $this->_height;

        $this->_im = imagecreate($this->_width, $this->_height);//创建画布

        //避免前景色和背景色过于接近，背景色（0-130）的随机范围与前景色（131-255）分开
        imagecolorallocate( $this->_im,
                            mt_rand(0,130),
                            mt_rand(0,130),
                            mt_rand(0,130));
                            
        $randString = $this->randString();
        
        for($i=0; $i<$this->_length; $i++){
            $fontColor = imagecolorallocate($this->_im,
                                            mt_rand(131,255),
                                            mt_rand(131,255),
                                            mt_rand(131,255));

            if (empty($this->_fontFilePath)) {
                imagestring($this->_im, 3, $i*($this->_fontSize+4)+4, mt_rand(0,8), $randString{$i}, $fontColor);
            } else {
                $heightMin = $this->_fontSize + ($this->_height - $this->_fontSize) * 0.05;
                $heightMax = $heightMin + ($this->_height - $this->_fontSize) * 0.9;
                imagettftext($this->_im, $this->_fontSize, 0, $i * $this->_fontSize + 8, mt_rand($heightMin, $heightMax), $fontColor ,$this->_fontFilePath, $randString{$i});
            }
        }

        $this->drawDot();//绘制噪点
        $this->drawLine();//绘制干扰线
        imagepng($this->_im);
        imagedestroy($this->_im);
        return $randString;//返回MD5加密后的验证码，可直接放入session
    }
}